// WebSocketHandler.js

class AuthenticatedWebSocket {
    constructor(url) {
        this.url = url;
        this.maxRetries = 3;
        this.retryCount = 0;
        this.retryInterval = 3000;
        this.connect();
    }

    connect() {
        this.token = localStorage.getItem('token');
        if (!this.token) {
            console.error('No auth token found');
            return;
        }

        //console.log('Initiating WebSocket connection...');
        this.ws = new WebSocket(this.url);

        this.ws.onopen = () => {
            //console.log('WebSocket connected, sending auth token');
            this.retryCount = 0;
            this.ws.send(JSON.stringify({
                type: 'auth',
                token: this.token
            }));
        };

        this.ws.onclose = (event) => {
            //console.log(`WebSocket closed with code: ${event.code}`);
            if (this.retryCount < this.maxRetries) {
                setTimeout(() => {
                    this.retryCount++;
                    //console.log(`Retrying connection (${this.retryCount}/${this.maxRetries})`);
                    this.connect();
                }, this.retryInterval);
            }
        };
    }

    handleMessage(event) {
        const data = JSON.parse(event.data);
        switch (data.type) {
            case 'auth_success':
                console.log('Authentication successful:', data.user);
                this.onAuthenticated && this.onAuthenticated(data.user);
                break;
            case 'auth_error':
                console.error('Authentication failed:', data.message);
                // 可能需要重定向到登录页面
                window.location.href = '/index.html';
                break;
            default:
                this.onMessage && this.onMessage(data);
        }
    }

    handleClose() {
        console.log('WebSocket disconnected');
        setTimeout(() => this.connect(), 5000);
    }

    handleError(error) {
        console.error('WebSocket error:', error);
    }

    send(data) {
        if (this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(JSON.stringify(data));
        }
    }
}

class WebSocketHandler {
    constructor() {
        this.ws = null;
        this.isConnected = false;
        this.protobufRoot = null;
        this.eventListeners = new Map();

        // 绑定方法
        this.onMessage = this.onMessage.bind(this);

        this.authWS = new AuthenticatedWebSocket('ws://10.10.3.27:8081');
        this.authWS.onAuthenticated = () => {
            // 认证成功后的初始化
        };
    }

    // 初始化 Protobuf
    async initProtobuf() {
        try {
            if (!$root?.mstf?.camb?.proto) {
                throw new Error('Missing protobuf definitions');
            }

            // 直接使用 $root 作为根对象
            this.protobufRoot = $root;

            // 添加验证步骤
            const messageType = 'mstf.camb.proto.ChassisMiscGroup';
            const MessageClass = this.protobufRoot.mstf.camb.proto.ChassisMiscGroup;

            if (!MessageClass) {
                throw new Error(`Message type ${messageType} not found`);
            }

            /*
            console.log('Protobuf initialized with message types:', {
                availableTypes: Object.keys(this.protobufRoot.mstf.camb.proto)
            });
            */

            return this.protobufRoot;
        } catch (error) {
            console.error('Proto init failed:', error);
            throw error;
        }
    }

    // 初始化连接
    async init() {
        try {
            // 先初始化 Protobuf
            await this.initProtobuf();

            const params = new URLSearchParams(window.location.search);
            const wsHost = params.get('wsHost') || window.location.hostname;
            const wsPort = params.get('wsPort') || '8055';
            const wsUrl = `ws://${wsHost}:${wsPort}`;
            const testUrl = "ws://192.168.58.128:8055";

            console.log("WebSocket initializing, url:", testUrl);

            return new Promise((resolve, reject) => {
                try {
                    this.ws = new WebSocket(testUrl);  // 先使用固定地址测试
                    this.ws.binaryType = 'arraybuffer';

                    this.ws.onopen = () => {
                        this.isConnected = true;
                        this.dispatchEvent('connectionStatusChange', true);
                        console.log('WebSocket connected successfully');
                        resolve();
                    };

                    this.ws.onclose = () => {
                        this.isConnected = false;
                        this.dispatchEvent('connectionStatusChange', false);
                        console.log('WebSocket connection closed');
                    };

                    this.ws.onerror = (error) => {
                        console.error('WebSocket error:', error);
                        reject(error);
                    };

                    this.ws.onmessage = this.onMessage;

                } catch (error) {
                    console.error('WebSocket initialization failed:', error);
                    reject(error);
                }
            });
        } catch (error) {
            console.error('Initialization failed:', error);
            throw error;
        }
    }

    // 发送消息前检查状态
    canSendMessage() {
        if (!this.isConnected) {
            console.warn('WebSocket is not connected');
            return false;
        }
        if (!this.protobufRoot) {
            console.error('Protobuf is not initialized');
            return false;
        }
        return true;
    }

    // 发送消息
    sendMessage(messageType, member, data) {
        if (!this.canSendMessage()) return;

        try {
            // 直接从 proto 命名空间获取消息类型
            const MessageClass = this.protobufRoot.mstf.camb.proto[messageType];

            if (!MessageClass) {
                throw new Error(`Message type ${messageType} not found in protobuf definitions`);
            }

            // 创建消息实例
            const payload = MessageClass.create(data);

            // 获取 RemoteXferMessage 类型
            const RemoteXferMessage = this.protobufRoot.mstf.camb.proto.RemoteXferMessage;
            const payloadField = this.getPayloadCamelField(member);

            const message = RemoteXferMessage.create({
                msgCnt: 1,
                version: "1.0",
                [payloadField]: payload,
                timeStamp: Math.floor(Date.now() / 1000)
            });

            const buffer = RemoteXferMessage.encode(message).finish();

            /*
            console.log('payload:', payload);
            console.log('Payload type:', messageType);
            console.log('Payload member: ', member, ', convert to js field:', payloadField);
            console.log('Payload data:', JSON.stringify(data, null, 2));
            console.log('Created payload:', JSON.stringify(payload.toJSON(), null, 2));

            console.log('message:', message);
            console.log('Buffer length:', buffer.length);
            console.log('Buffer content:', Array.from(buffer));

            const decoded = RemoteXferMessage.decode(buffer);
            console.log('Decoded message:', decoded.toJSON());

            console.log('Sending buffer:', buffer);
            */

            // 发送前记录日志
            /*
            console.log('Sending message:', {
                type: messageType,
                payload: message.toJSON()
            });
            */

            this.ws.send(buffer);
        } catch (error) {
            console.error('Failed to send message:', error, {
                messageType,
                data,
                availableTypes: this.protobufRoot?.mstf?.camb?.proto ?
                Object.keys(this.protobufRoot.mstf.camb.proto) :
                'No types available'
            });
        }
    }

    // 获取payload字段名
    getPaySnakeloadField(messageType) {
        // 将 PascalCase 转换为 snake_case
        const snakeCase = messageType
            .replace(/\.?([A-Z])/g, (x,y) => "_" + y.toLowerCase())
            .replace(/^_/, "");
        return snakeCase;
    }

    getPayloadCamelField(messageType) {
        // Clean up input string
        messageType = messageType.trim();

        // Split the string by underscore
        const parts = messageType.split('_');

        // Process each part
        return parts.map((part, index) => {
            // Skip empty parts from consecutive underscores
            if (!part) return '';

            // Keep the first part lowercase if it's the beginning
            if (index === 0) {
                return part.toLowerCase();
            }

            // If the part contains numbers, keep it as is
            if (/\d/.test(part)) {
                return '_' + part;
            }

            // Capitalize the first letter, keep the rest in original case
            return part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
        }).join('');
    }

    // 便捷方法修改
    querySystemInfo() {
        this.sendMessage("SystemInfoGroup", "system_info", {
            query: {}  // QuerySystemInfo 消息
        });
    }

    queryChassisInfo() {
        this.sendMessage("PeriphInfoGroup", "periph_info", {
            query: {}  // 假设有 QueryPeriphInfo 消息
        });
    }

    refreshData() {
        // 根据实际协议定义发送刷新消息
        this.querySystemInfo();
        this.queryChassisInfo();
    }

    // 消息处理
    onMessage(event) {
        if (event.data instanceof ArrayBuffer) {
            chassisReceiveData.handleBinaryMessage(event.data);
        } else {
            console.log('Received text message:', event.data);
        }
    }

    // 断开连接
    disconnect() {
        if (this.ws) {
            this.ws.close();
            this.ws = null;
            this.isConnected = false;
        }
    }

    // 事件监听器管理
    addEventListener(event, callback) {
        if (!this.eventListeners.has(event)) {
            this.eventListeners.set(event, new Set());
        }
        this.eventListeners.get(event).add(callback);
    }

    removeEventListener(event, callback) {
        const listeners = this.eventListeners.get(event);
        if (listeners) {
            listeners.delete(callback);
        }
    }

    dispatchEvent(event, data) {
        const listeners = this.eventListeners.get(event);
        if (listeners) {
            listeners.forEach(callback => callback(data));
        }
    }

    toggleConnection() {
        if (isConnected) {
            disconnectWebSocket();
        } else {
            initWebSocket();
        }
    }

    updateConnectionStatus(connected) {
        console.log('Update webSocket connection status:', connected);
        const statusButton = document.getElementById('connection-status');
        if (connected) {
            statusButton.textContent = 'Connected';
            statusButton.style.backgroundColor = '#2ecc71';
            isConnected = true;
        } else {
            statusButton.textContent = 'Connect';
            statusButton.style.backgroundColor = '#e74c3c';
            isConnected = false;
        }
    }

    sendProtobufMessage(messageType, data) {
        if (ws && ws.readyState === WebSocket.OPEN) {
            const Message = protobufRoot.lookupType(messageType);
            const message = Message.create(data);
            const buffer = Message.encode(message).finish();
            ws.send(buffer);
        } else {
            console.log('WebSocket is not connected');
        }
    }

}

// 创建全局实例
const webSocketHandler = new WebSocketHandler();

// 导出到全局作用域
if (typeof window !== 'undefined') {
    window.webSocketHandler = webSocketHandler;
}

// CommonJS 模块导出
if (typeof module !== 'undefined' && module.exports) {
    module.exports = {
        WebSocketHandler,
        webSocketHandler
    };
}
